/**
 * @file circuit_master.c
 * @author Linquan  
 * @brief 管理整个系统中所有回路的根节点,提供回路节点最上层的函数接口。
 * @version 1.0
 * @date 2024-08-14
 * 
 * @copyright Copyright (c) 2024
 * 
 */
#include "stdio.h"

#include "master_ctr_circuit_node.h"
#include "../circuit_node/circuit_config.h"

#include  "../config/config_by_device_type.h"




/**
 * @brief 本机主节点树
 * 
 */
master_global_mangment_t MasterMangmentData;




/**
 * @brief Create a circuit node by table object
 * 创建一个回路，对回路上的节点分配空间
 * @param table_head 
 * @return int 
 */
int create_circuit_node_by_table(dev_type_config_info_t* type_cfg_info, cfg_circuit_overview_t table_head)
{
    /**> 1、依次传入每个回路的ID和回路节点数量 */
    uint32_t        ID = table_head.circuit_ID;           /* 回路ID  */ 
    uint32_t        node_num = table_head.circuit_node_num;    /* 回路包含的节点数量*/
    
    if(ID >= SELF_CIRCUIT_MAX ) return -1;

     /**> 2、分配 circuit_node_t *回路节点数量的空间给该回路指针，形成一个空回路节点数组。*/ 
     if (type_cfg_info->node_tree1 != NULL)
     {
         type_cfg_info->node_tree1[ID].branch_ptr = (circuit_node_t*)calloc(node_num, sizeof(circuit_node_t));
     }
     else 
     {
        error_log("the node: ID%d ,node_num %d 's node_tree_ptr is null",ID, node_num);
     }
     

    /**> 3、保存配置文件的回路中节点数量 */
    if(type_cfg_info->cfg_node_num_ptr != NULL)
    {
        type_cfg_info->cfg_node_num_ptr[ID] = node_num;
    }
    else 
    {
        error_log("the node: ID%d ,node_num %d 's cfg_node_num_ptr is null",ID, node_num);
    }

     debug_log(" 配置文件中回路的节点数量： %d \n",type_cfg_info->cfg_node_num_ptr[ID] );
}




/**
 * @brief 将配置的节点信息填入节点中，当配置中出现任何异常，立刻退出配置文件，并记录异常位置到文件中。
 * 
 * @param config_info 
 * @return int 
 *            找不到操作函数，返回 ERROR（-1）
 *            正常结束 返回 TRUE(1)
 */
int trans_config_data_to_node(dev_type_config_info_t* type_cfg_info, cfg_node_info_t node_config_info)
{
    /**> 1、整理相关信息 */ 
    node_operate_irf_t       *op_ptr;       /** 模块的操作函数指针 */
    circuit_node_type_t      node_type;     /** 节点类型 */
    circuit_node_t           *node_ptr;     /** 节点指针 */


    if (type_cfg_info == NULL  )
    {
        error_log("type_cfg_info ptr is null");
        return ERROR;
    }

    uint32_t ID     = node_config_info.dev_addr.circuit_ID;
    uint32_t index  = type_cfg_info->node_tree1[ID].branch_node_number;
    node_type       =  node_config_info.node_type;
    uint32_t op_result = 0;

    //debug_log("index %d \n",index);

    /**> 2、获得一个需要配置的节点 */
    node_ptr =  &type_cfg_info->node_tree1[ID].branch_ptr[index];

    /**> 3、根据节点找到对应的操作函数组 */
    op_ptr = get_op_irf_by_circuit_node_type(node_type);

    /** 4、调用init函数，传入配置信息 */
    if(op_ptr)
    {  
          op_result = op_ptr->irfInit(node_ptr, &node_config_info);  

        if((op_result & ERR_MASK) != 0)
        {                  
            error_log("node type:[%d] init function is not sucess. the result is : %#X ",\
                    node_type, op_result);
        }
        else
        {
            type_cfg_info->node_tree1[ID].branch_node_number++;
        }
    }
    else
    {
        error_log("node type: %d's op function is not support!",node_type);
        return ERROR;
    }


    // 5、进行其他操作{ 添加91A节点到 链表中}，该回路索引加一
    if(type_cfg_info->node_add_callback != NULL)
    {
        type_cfg_info->node_add_callback(node_ptr, op_result);
    }
   
    return TRUE;
}


/**
 * @brief 检查 配置文件中的节点数量，是否与配置结束之后的节点数量相等
 * 
 * @return uint8_t 均相等：0，不相等：1
 */
uint8_t check_config_node_num_is_equl(dev_type_config_info_t* type_cfg_info)
{
     for(int i = 0; i < type_cfg_info->ciucuit_nume; i++)
    {
        if(type_cfg_info->cfg_node_num_ptr[i] !=  type_cfg_info->node_tree1[i].branch_node_number)
        {
          return FLASE;
        }
    }
    return TRUE;
}



/**
 * @brief Get the circuit node number object
 *         在配置成功后，获得 某个回路的节点数量
 * 
 * @param circuit_ID  回路ID 
 * @return int 
 */
int get_master_tree_node_number(uint8_t circuit_ID)
{
    if(!is_config_sucess())
    {
        error_log("config is not sucess");
        return -1;
    }

    if(circuit_ID >= SELF_CIRCUIT_MAX )
    {
        return -1;
    }
    
    return MasterMangmentData.master_node_tree[circuit_ID].branch_node_number;
}







/**
 * @brief Get the node from master tree object
 *  从主节点树中，通过多级地址 找到对应节点。
 *  传入 多级地址变量，返回变量中的节点指针，如果为空，则查找失败。
 * 
 *  多级地址：一个节点地址由 回路号+设备索引号确定。在多个设备级联是，多个回路号+设备索引形成多级地址。
 *     excample：   某一个节点的多级地址： 【（回路1，索引1），（回路3，索引5）】
 * @param 
 * @return addr_ptr->node_ptr == null：fail 
 */
int get_node_from_master_tree_by_muti_addr(muti_addr_t *addr_ptr)
{
    uint32_t  master_ID;            /* 主回路ID */
    uint32_t  master_node_index;    /* 主回路节点索引号 */ 
    circuit_node_t *temp_node = NULL;

    /**> 初始化 node指针 */
    addr_ptr->node_ptr = NULL;

    if(!is_config_sucess())
    {
        error_log("config is not sucess");
        return ERROR;
    }

    if(addr_ptr->addr_arry_ptr == NULL || addr_ptr->addr_num == 0 )
    {
        error_log("the ptr is null or addr number is  zero!");
        return ERROR;
    }
 

   /** 根据传入的地址数组，进行第一次地址剥离，从主节点树上，
    * 找到第一级节点，然后把节点传入 circuit_node文件中，根据设备类型进行地址依次剥离 */
    master_ID           = addr_ptr->addr_arry_ptr->circuit_ID;
    master_node_index   = addr_ptr->addr_arry_ptr->circuit_node_index;


    /**>  查找算法，当查找的节点索引小于 该回路的最大节点数，则遍历查找该回路的每个节点具体索引，找到该节点 */
    if(master_node_index < MasterMangmentData.master_node_tree[master_ID].branch_node_number)
    {
         temp_node = &MasterMangmentData.master_node_tree[master_ID].branch_ptr[master_node_index];
    }
    else
    {
       // 遍历
        for(int i = 0; i < MasterMangmentData.master_node_tree[master_ID].branch_node_number; i ++)
        {
            if (MasterMangmentData.master_node_tree[master_ID].branch_ptr[i].node_addr.circuit_node_index \
                    ==  master_node_index)
            {
                 temp_node = &MasterMangmentData.master_node_tree[master_ID].branch_ptr[i];
                 break;
            }
        }
    }

    if(temp_node == NULL)
    {
       return ERROR;
    }

    /** 调用 circuit——node 中的函数进行地址进一步剥离 */

    // muti_addr_t muti_addr;
    addr_ptr->addr_num--;        /** 地址级数剥离两位 */
    addr_ptr->addr_arry_ptr += 1;   /** 地址指针偏移两位 */
    addr_ptr->node_ptr = temp_node; /** 节点指针指向新的节点位置 */

    //debug_log(" 1--- %s  \n",temp_node->dev_description);

    /** 当多级地址级数不为0，认为 节点上还有下挂节点 */
    if(addr_ptr->addr_num != 0)
    {
         get_node_by_muti_addr(addr_ptr);
    }
    else
    {
        info_log("the addr number is zero! find is finish");
    }
    return TRUE;
}



/**
 * @brief Get the node from master tree by 90a dev addr object
 * 专为 91a 设备的地址所编写的节点查询函数。
 * 这种查询方式，约定90a连接的下级回路，不存在不同回路有设备重号的情况。
 * 最大三级地址，不区分回路编号，使用设备索引号进行查询.
 * @param dev_addr 
 * @return int 
 */

int get_node_from_master_tree_by_91a_dev_addr( find_91a_node_t *node_find)
{
    #define ID(X)        (X-1) 

    /**> 为了保证输入参数的正确性，使用int16 来接受uint8类型的数据 */
    int16_t  master_id_temp = ID(node_find->dev_addr.master_index);
    int16_t  node_id_temp   = ID(node_find->dev_addr.node_index);
    int16_t  relay_id_temp  = node_find->dev_addr.relay_index;

    if(node_find->dev_addr.relay_index != RELAY_ORDER_INVAILD)
    {   // 如果中继模块值有效，则减一，如果无效则保留原值
        relay_id_temp = ID(node_find->dev_addr.relay_index);
    }
   

    node_find->node_ptr = NULL;
    circuit_node_t *temp_node = NULL;


    if(master_id_temp < 0 || relay_id_temp < 0 || node_id_temp < 0)
    {
        error_log("some id is little than 0. id: %d, %d,%d",master_id_temp, relay_id_temp, node_id_temp);
        return ERROR;
    }


    if(!is_config_sucess())
    {
        error_log("config is not sucess");
        return ERROR;
    }

    /**> 1、遍历90a的回路，期望找到 91a的节点，91a节点只接在can总线上，所以只遍历两条can总线即可 
     * 
     *  假定 90A将来会同时 连接 can总线、485总线。遍历四条总线上的节点
    */
    for(int circuit_id = 0; circuit_id <= SELF_CIRCUIT_MAX; circuit_id++ )
    { 
        uint8_t branch_node_number = \
                MasterMangmentData.master_node_tree[circuit_id].branch_node_number;

        if( 0 == branch_node_number)
        {
            info_log("this branch's number is 0 \n");
            continue;
        }
        
        /**> 2、该回路节点数不为0，则遍历该回路中的节点，找91a类型的节点，  */
        for(int node_index = 0; node_index < branch_node_number; node_index++)
        {
            temp_node = &MasterMangmentData.master_node_tree[circuit_id].branch_ptr[node_index];

            /**> 3、在这个回路中：找到该主机号的91A的节点 */
            if(temp_node->node_type == TYPE_CTR_CW1320_91A \
                && temp_node->node_addr.circuit_node_index == master_id_temp)
            {    
                debug_log("91a description %s \n ",temp_node->dev_description);
 
                CONFIG_INFO_TYPE(TYPE_CTR_CW1320_91A) *node_cfg =\
                            ( CONFIG_INFO_TYPE(TYPE_CTR_CW1320_91A) *)temp_node->node_config_data;


                /**> 4、如果中继号等于0X5AA5(无效)，则遍历91a中回路里非中继模块设备 */ 
                if(relay_id_temp == RELAY_ORDER_INVAILD)
                {
                    /**> 4.1、遍历 回路 
                     * 
                     * 假定 将来91A会使用 二总线、can、485等总线，在这些总线中按顺序遍历节点。
                    */
                    for(int circuit_id_91a = 0; circuit_id_91a < MOD_91A_CIRCUIT_MAX; circuit_id_91a ++)
                    {      
                        uint8_t node_number_91a =\
                            node_cfg->mod_91a_node_tree_ptr[circuit_id_91a].branch_node_number;
                        
                         /**> 4.2、遍历 回路中的节点 */
                        for(int dev_index = 0; dev_index < node_number_91a; dev_index++)
                        {
                           temp_node = &node_cfg->mod_91a_node_tree_ptr[circuit_id_91a].branch_ptr[dev_index];            

                            if(temp_node->node_addr.circuit_node_index == node_id_temp)
                            {
                                debug_log("1 invaild temp node%s \n ",temp_node->dev_description);

                                node_find->node_ptr = temp_node;
                                /**> 找到目标节点 */
                                return TRUE;
                            }
                        }  
                    }
                }
                else /**> 5、 否则遍历中继模块中的节点 */
                {
                    /**> 5.1、遍历 回路*/
                    for(int circuit_id_91a = 0; circuit_id_91a < MOD_91A_CIRCUIT_MAX; circuit_id_91a ++)
                    {
                        
                       debug_log("circuit_id_91a %d \n ",circuit_id_91a);

                        uint8_t node_number_91a =\
                            node_cfg->mod_91a_node_tree_ptr[circuit_id_91a].branch_node_number;

                         /**> 5.2、遍历 回路中的节点，找中继模块 */
                        for(int dev_index = 0; dev_index < node_number_91a; dev_index++)
                        {     
                            temp_node =\
                                &node_cfg->mod_91a_node_tree_ptr[circuit_id_91a].branch_ptr[dev_index];            

                            if(temp_node->node_type == TYPE_MOD_RELAY)
                            {
                                
                                CONFIG_INFO_TYPE(TYPE_MOD_RELAY) *node_relay_cfg =\
                                    (CONFIG_INFO_TYPE(TYPE_MOD_RELAY)*)temp_node->node_config_data;

                                temp_node =  &node_relay_cfg->node_tree_ptr.branch_ptr[node_id_temp];
                                
                                node_find->node_ptr = temp_node;
                                return TRUE;
                            }
                        }  
                    }
                     error_log("do not find the node in relay mode");
                }

                
            }
        }

    }
  



}












